package com.smsc.headend.task.engine.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.smsc.headend.common.utils.CosemUtils;
import com.smsc.headend.common.utils.RedisUtils;
import com.smsc.headend.module.common.entity.DeviceOperation;
import com.smsc.headend.module.data.enums.DictionaryType;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.protocol.ProtocolType;
import com.smsc.headend.module.protocol.ansi.AnsiByteBuffer;
import com.smsc.headend.module.protocol.ansi.AnsiData;
import com.smsc.headend.module.protocol.cosem.util.ByteNumberUtils;
import com.smsc.headend.module.protocol.cosem.util.ByteUtils;
import com.smsc.headend.module.protocol.cosem.util.CosemXmlUtils;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.module.protocol.cosem.bo.CosemData;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.CosemXmlService;
import com.smsc.headend.task.engine.service.asset.AssetService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Set;

@Service
@Slf4j
public class CosemXmlServiceImpl implements CosemXmlService {
    @Autowired
    RedisUtils redisUtils;

    @Autowired
    FeignAssetManagementService assetManagementService;
    @Autowired
    AssetService assetService;

    @Override
    public DeviceData handlerXML(Task task, AtomicTask atomicTask, String resultCosemXml) {
        if (atomicTask == null) {
            log.error("callback message's atomic task not exists,{}", task.getTaskNo());
            return null;
        }
        DeviceOperation operationDict = assetService.getDictionary(atomicTask.getOperationId(), DictionaryType.Operation.getType());
        if (operationDict == null) {
            log.error("System configuration error,", atomicTask);
            return null;
        }

        DeviceData data = null;
        // connector 返回的不同规约的数据是json格式，除cosem，格式：{"1042001": byte[]}
        if(JSONUtil.isJson(resultCosemXml)) {
            JSONObject jsonObject = JSONUtil.parseObj(resultCosemXml);
            Set<String> keys = jsonObject.keySet();
            String protocolId = keys.stream().findFirst().get();
            if(Convert.toLong(protocolId) == ProtocolType.ANSI_C12_18_Protocol.getProtocolId()) {
                data = new AnsiData(new AnsiByteBuffer(jsonObject.getStr(protocolId).getBytes(StandardCharsets.ISO_8859_1)));
            }
        } else {
            //TODO： 根据task信息判断属于COSEM后使用
            data = CosemXmlUtils.translateCosemXml(resultCosemXml);
        }
        return data;
    }


    /**
     * @param type  Cosem Simple XMl Element name. UInt32,etc
     * @param value
     * @return
     */
    @Override
    public Object getData(String type, String value) {
        if ("Int8".equalsIgnoreCase(type)) {
            return Convert.toStr(ByteUtils.hexStringToByte(value)[0]);
        }
        if ("Int16".equalsIgnoreCase(type)) {
            return Convert.toStr(ByteNumberUtils.byte2ToShort(ByteUtils.hexStringToByte(value)));
        }
        if ("Int32".equalsIgnoreCase(type)) {
            if (value.contains("-")) {
                String[] valueArr = value.split("-");
                Integer result = -1 * Integer.parseInt(valueArr[1], 16);
                return Convert.toStr(result);
            }
            return Convert.toStr(ByteNumberUtils.byte4ToInt(ByteUtils.hexStringToByte(value)));
        }
        if ("Int64".equalsIgnoreCase(type)) {
            if (value.contains("-")) {
                String[] valueArr = value.split("-");
                long result = -1 * Long.parseLong(valueArr[1], 16);
                return Convert.toStr(result);
            }
            return Convert.toStr(ByteNumberUtils.byte8ToLong(ByteUtils.hexStringToByte(value)));
        }

        if ("UInt8".equalsIgnoreCase(type) || "Enum".equalsIgnoreCase(type) || "UInt16".equalsIgnoreCase(type) || "UInt32".equalsIgnoreCase(type) || "UInt64".equalsIgnoreCase(type)) {
            BigInteger uintData = ByteNumberUtils.strToUint(type, value);
            value = String.valueOf(uintData);
            return value;
        }
        if ("OctetString".equalsIgnoreCase(type) || "String".equalsIgnoreCase(type) || "Boolean".equalsIgnoreCase(type)) {
            return value;
        }
        if ("DateTime".equalsIgnoreCase(type)) {
            return CosemUtils.parseOctStringDataTime(value);
        }
        if ("Time".equalsIgnoreCase(type)) {
            return CosemUtils.parseOctStringTime(value);
        }
        if ("BitString".equalsIgnoreCase(type)) {
            return Convert.toStr(value);
        } else if("Date".equalsIgnoreCase(type)) {
            if (CosemUtils.isLocalDate(Convert.toStr(value))) {
                value = CosemUtils.parseOctStringDateX(Convert.toStr(value));
            }
            return value;
        } else if ("Float32".equalsIgnoreCase(type)) {
            return Float.intBitsToFloat(ByteNumberUtils.getInt32(value));
        } else if ("Float64".equalsIgnoreCase(type)) {
            return Double.longBitsToDouble(ByteNumberUtils.getInt64(value));
        }
        return null;
    }

}